#include "EventLoop.h"
#include "Logger.h"
#include <unistd.h>
#include <sys/eventfd.h>

// 1. 执行任务池中的所有任务
void EventLoop::RunAllTask()
{
    // 细节：为什么要交换任务而不直接操作_tasks？？
    // 锁的粒度控制：通过交换，锁的持有时间仅覆盖 交换操作本身，而不是整个任务执行过程。 后续遍历 functor 执行任务时不再需要锁，避免阻塞其他线程向 _tasks 添加新任务。
    //线程安全：其他线程调用 QueueInLoop 时，可以向新的空 _tasks 添加任务，而当前线程处理的是交换出的旧任务集合。 避免遍历 _tasks 时被其他线程修改导致竞态条件。
    std::vector<Functor> functor;
    {
        std::unique_lock<std::mutex> lock(_mutex);
        functor.swap(_tasks);
    }
    for (auto f : functor)
        f();
}

// 2. 创建一个事件通知描述符
int EventLoop::CreateEventFd()
{
    int efd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
    if (efd < 0)
    {
        perror("EVENTFD FAILED");
        abort();
    }
    return efd;
}

// 3. 读取事件通知描述符
void EventLoop::ReadEvent()
{
    uint64_t res = 0;
    int ret = read(_eventfd, &res, sizeof(res));
    if (ret < 0)
    {
        if (errno == EINTR || errno == EAGAIN)
            return;
        ERR_LOG("READ EVENTFD FAILED");
        abort();
    }
}

// 4. 向_eventfd中写入数据，唤醒IO事件
void EventLoop::WeakUpEventFd()
{
    uint64_t val = 1;
    int ret = write(_eventfd, &val, sizeof(val));
    if (ret < 0)
    {
        if (errno == EINTR)
            return;
        ERR_LOG("像eventfd写入数据失败");
        abort();
    }
}

EventLoop::EventLoop()
    : _thread_id(std::this_thread::get_id()),
      _eventfd(CreateEventFd()),
      _event_channel(new Channel(this, _eventfd)),
      _timer_wheel(this)
{
    _event_channel->SetReadCallback(std::bind(&EventLoop::ReadEvent, this));
    _event_channel->EnableRead();
}

// 1. 运行当前任务
void EventLoop::RunInLoop(const Functor &cb)
{
    if (IsInLoop())
        return cb();
    return QueueInLoop(cb);
}

// 2. 将任务压入任务池
void EventLoop::QueueInLoop(const Functor &cb)
{
    {
        std::unique_lock<std::mutex> lock(_mutex);
        _tasks.push_back(cb);
    }
    WeakUpEventFd();
}

// 3. 判断当前线程是否是EventLoop对应的线程
bool EventLoop::IsInLoop()
{
    return _thread_id == std::this_thread::get_id();
}

// 4. 添加/修改描述符的事件监控
void EventLoop::UpdataEvent(Channel *channel)
{
    _poller.UpdataEvent(channel);
}

// 5. 移除描述符的事件监控
void EventLoop::RemoveEvent(Channel *channel)
{
    _poller.RemoveEvent(channel);
}

// 6. 添加定时任务
void EventLoop::TimerAdd(uint64_t id, uint32_t delay, const TaskFunc &cb)
{
    return _timer_wheel.TimerAdd(id, delay, cb);
}

// 7. 刷新当前定时任务在时间轮的位置
void EventLoop::TimerRefresh(uint64_t id)
{
    return _timer_wheel.TimerRefresh(id);
}

// 8. 取消定时任务
void EventLoop::TimerCancel(uint64_t id)
{
    return _timer_wheel.TimerCancel(id);
}

bool EventLoop::HasTimer(uint64_t id)
{
    return _timer_wheel.HasTimer(id);
}

// 10. 启动事件循环    三步走--事件监控-》就绪事件处理-》执行任务
void EventLoop::Start()
{
    while (1)
    {
        // 1. 事件监控
        std::vector<Channel *> actives;
        _poller.Poll(&actives);
        // 2. 就绪事件处理
        for (auto &channel : actives)
            channel->HandleEvent();
        // 执行任务池中所有的任务
        RunAllTask();
    }
}